#!/bin/bash
##### @author itluck  #####
##### v1.0 2025年8月11日 #####
set -euo pipefail

# 打包参数
GIT_START="4c093e6ea62316092953008b856859b6929b670e" #开始打包的日志ID
GIT_END="68ef14f1157eefbd855fdd377a1da1200c9b626a" #结束打包的日志ID
IGNORE=("applicationContext.xml" "log4j.xml" "web.xml") #忽略的文件，注意不需要写逗号,

# 配置参数
PROJECT_DIR="D:/nky-code/pbjd-project/int_gz" #git项目根路径
MODULE_DIR="authority" #子模块名称，没有子目录可以为空字符""
ARTIFACT_ID="authority" #pom的artifactId值
PACK_NAME="changes_$(date +%Y%m%d%H%M)"
TARGET_DIR="$PROJECT_DIR/$MODULE_DIR/target"
OUTPUT_DIR="$TARGET_DIR/$PACK_NAME" #打包输出目录
LOG_FILE="$OUTPUT_DIR/change_log.txt" #打包日志

mkdir -p $OUTPUT_DIR

echo "变更文件记录：$(date)" > "$LOG_FILE"
echo "开始比对git变更记录$GIT_START..$GIT_END"  | tee -a "$LOG_FILE"
# 创建日志文件
echo "=================================="  | tee -a "$LOG_FILE"

# 获取用户输入
#read -p "请输入起始版本（默认HEAD~1）: " GIT_START
#read -p "请输入结束版本（默认HEAD）: " GIT_END
#GIT_START=${GIT_START:-"HEAD~1"}
#GIT_END=${GIT_END:-"HEAD"}

# 验证版本范围
if ! git rev-parse "$GIT_START" >/dev/null 2>&1 || ! git rev-parse "$GIT_END" >/dev/null 2>&1; then
  echo "错误：无效的版本范围 $GIT_START..$GIT_END" | tee -a "$LOG_FILE"
  exit 1
fi

# 1. 输出并记录所有变更文件
echo "【Java类变更】" | tee -a "$LOG_FILE"
git diff --name-only --diff-filter=ACMR "$GIT_START".."$GIT_END" -- "${MODULE_DIR:+${MODULE_DIR}/}src/main/java/" | tee -a "$LOG_FILE"

echo -e "\n【Web资源变更】" | tee -a "$LOG_FILE"
git diff --name-only --diff-filter=ACMR "$GIT_START".."$GIT_END" -- "${MODULE_DIR:+${MODULE_DIR}/}src/main/webapp/" | tee -a "$LOG_FILE"

echo -e "\n【配置文件变更】" | tee -a "$LOG_FILE"
git diff --name-only --diff-filter=ACMR "$GIT_START".."$GIT_END" -- "${MODULE_DIR:+${MODULE_DIR}/}src/main/resources/" | tee -a "$LOG_FILE"

echo "共找到 $(grep -c "src/main" "$LOG_FILE") 个变更文件，开始拷贝处理" | tee -a "$LOG_FILE"

# 2. 处理class变更文件
process_class_files() {
  local file_type=$1
  local target_dir=$PROJECT_DIR/${MODULE_DIR:+${MODULE_DIR}/}target/$ARTIFACT_ID

  echo "【处理$file_type文件】" | tee -a "$LOG_FILE"
  grep "src/main/java" "$LOG_FILE" | while IFS= read -r line; do
      echo "正在处理文件: $line" | tee -a "$LOG_FILE"

      # 获取最终编译文件的文件名
      full_filename="${line##*/}"       # 先获取完整文件名：Expert.java
      filename="${full_filename%.*}"    # 去掉扩展名：Expert
      file_suffix=$(get_suffix_name $full_filename) # 获取后缀，例如java、xml，防止静态文件写在java目录下

      # 获取最终相对编译文件的父目录
      classes_path="${line#*src/main/java/}"  # 删除到 src/main/java/ 第一次出现的位置
      classes_path=$(normalize_path $classes_path)           # 再去掉文件名

      #创建输出目录
      mkdir -p "$OUTPUT_DIR/WEB-INF/classes/$classes_path"

      cp -r "$target_dir/WEB-INF/classes/$classes_path/$filename$file_suffix" "$OUTPUT_DIR/WEB-INF/classes/$classes_path/$filename$file_suffix"

      # 只有后缀是 class 时才执行内部类查找和拷贝
      if [ "$file_suffix" = ".class" ]; then
          # 遍历这个目录下，判断是否存在内部类文件，也要一并拷贝
          found_files=()
          while IFS= read -r -d $'\0' file; do
              found_files+=("$file")
          done < <(find "$target_dir/WEB-INF/classes/$classes_path" -maxdepth 1 -name "${filename}\$*" -print0)

          # 处理找到的文件
          if [ ${#found_files[@]} -gt 0 ]; then
              echo "找到 ${#found_files[@]} 个内部类文件："
              for file in "${found_files[@]}"; do
                  nbl_name=${file##*/} #内部类名
                  cp -r "$file" "$OUTPUT_DIR/WEB-INF/classes/$classes_path/$nbl_name"
              done
          else
              echo "$filename 无内部类文件"
          fi
      else
          :
      fi
  done
}


# 处理配置文件
process_resources_files() {
  local file_type=$1
  local target_dir=$PROJECT_DIR/${MODULE_DIR:+${MODULE_DIR}/}target/$ARTIFACT_ID

  echo "【处理$file_type文件】" | tee -a "$LOG_FILE"
  grep "src/main/resources" "$LOG_FILE" | while IFS= read -r line; do
       echo "正在处理文件: $line" | tee -a "$LOG_FILE"

       filename="${line##*/}"       # 获取完整文件名：dubbo-consumer.xml

       # 获取最终相对编译文件的父目录
       resources_path="${line#*src/main/resources/}"  # 删除到 src/main/java/ 第一次出现的位置
       resources_path=$(normalize_path $resources_path)           # 再去掉文件名

       #创建输出目录
       mkdir -p "$OUTPUT_DIR/WEB-INF/classes/$resources_path"

       cp -r "$target_dir/WEB-INF/classes/$resources_path/$filename" "$OUTPUT_DIR/WEB-INF/classes/$resources_path/$filename"
  done
}


# 处理静态文件
process_web_files() {
  local file_type=$1
   local target_dir=$PROJECT_DIR/${MODULE_DIR:+${MODULE_DIR}/}target/$ARTIFACT_ID

   echo "【处理$file_type文件】" | tee -a "$LOG_FILE"
   grep "src/main/webapp" "$LOG_FILE" | while IFS= read -r line; do
       echo "正在处理文件: $line" | tee -a "$LOG_FILE"

       filename="${line##*/}"       # 获取完整文件名：updatePwd.js

       # 获取最终相对编译文件的父目录
       webapp_path="${line#*src/main/webapp/}"  # 删除到 src/main/java/ 第一次出现的位置
       webapp_path=$(normalize_path $webapp_path)           # 再去掉文件名

       #创建输出目录
       mkdir -p "$OUTPUT_DIR/$webapp_path"

       cp -r "$target_dir/$webapp_path/$filename" "$OUTPUT_DIR/$webapp_path/$filename"
   done
}


# 获取编译后的文件最终后缀
get_suffix_name() {
    local fullname="$1"
    local suffix="${fullname##*.}"

    if [ "$suffix" = "java" ]; then
        echo ".class"
    else
        echo ".$suffix"
    fi
}

# 通过path，删除后面的文件名
normalize_path() {
    local path="$1"
    if [[ "$path" == */* ]]; then
        echo "${path%/*}"
    else
        echo ""
    fi
}

# 开始处理各类文件
if grep -q "src/main/java" "$LOG_FILE"; then
  process_class_files "Java类"
fi

if grep -q "src/main/resources" "$LOG_FILE"; then
  process_resources_files "配置"
fi


if grep -q "src/main/webapp" "$LOG_FILE"; then
  process_web_files "Web资源"
fi

# 剔除忽略的文件
echo "进行删除忽略的补丁文件..." | tee -a "$LOG_FILE"

# 遍历数组并删除匹配的文件
for pattern in "${IGNORE[@]}"; do
  find $OUTPUT_DIR -name $pattern -print0 | xargs -0 rm -f
done

# 完成输出
echo -e "\n操作完成！" | tee -a "$LOG_FILE"
echo "变更记录: $LOG_FILE" | tee -a "$LOG_FILE"
echo "文件输出目录: $OUTPUT_DIR" | tee -a "$LOG_FILE"
